//@author A0096566M
#include "mycompleter.h"


//Filter out Up and Down keys, to implement going back to prevoius command.
bool MyCompleter::eventFilter(QObject *obj, QEvent *event)
{
    if (event->type() == QEvent::KeyPress) {
        QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event);
        switch(keyEvent->key()) {
            case Qt::Key_Up:
                if(historyIndex<inputHistory.size()-1 || historyIndex == -1)
                    historyIndex++;

                qDebug() << historyIndex;
                qDebug() << inputHistory.size();
                if(historyIndex>=0 && historyIndex<inputHistory.size()){
                    ((MyLineEdit*)this->mLineEdit)->setText(QString::fromStdString((inputHistory.at(historyIndex))));
                }

                return true;
            case Qt::Key_Down:
            //Up/Down for input History
                if(historyIndex>=0)
                    historyIndex--;
                if(historyIndex>=0 && historyIndex<inputHistory.size())
                    ((MyLineEdit*)this->mLineEdit)->setText(QString::fromStdString((inputHistory.at(historyIndex))));

                return true;
            break;
        }
        return QCompleter::eventFilter(obj, event);;
    } else {
        return QCompleter::eventFilter(obj, event);
    }
}

MyLineEdit::MyLineEdit(QWidget *parent)
    : QTextEdit(parent), c(0)
{
    this->setAcceptRichText(false);
    this->installEventFilter(this);
}

MyLineEdit::~MyLineEdit()
{
}

void MyLineEdit::setCompleter(MyCompleter *completer)
{
    if (c)
        QObject::disconnect(c, 0, this, 0);
    c = completer;
    c->mLineEdit = this;
    if (!c)
        return;
    c->setWidget(this);
    connect(completer, SIGNAL(activated(const QString&)), this, SLOT(insertCompletion(const QString&)));
}

MyCompleter *MyLineEdit::completer() const
{
    return c;
}

void MyLineEdit::insertCompletion(const QString& completion)
{
    this->setText(completion);
    this->setText(this->toPlainText());
    selectAll();
}

bool MyLineEdit::eventFilter(QObject *obj, QEvent *event)
{
    if (event->type() == QEvent::KeyPress) {
        QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event);
        switch(keyEvent->key()) {
            case Qt::Key_Enter:
            case Qt::Key_Return:
                returnPressed();
                this->completer()->historyIndex = -1;
                return true;
            break;
        }
        return false;
    } else {
        return QObject::eventFilter(obj, event);
    }
}


void MyLineEdit::keyPressEvent(QKeyEvent *e)
{
    if (c && c->popup()->isVisible())
    {
        // The following keys are forwarded by the completer to the widget
        switch (e->key())
        {
        case Qt::Key_Enter:
        case Qt::Key_Return:
            //Select suggestion
            c->selectedIndex = c->index;
        case Qt::Key_Escape:
            e->ignore();
            c->index = -1;
            return; // Let the completer do default behavior
        case Qt::Key_Tab:
            c->index += 1;
            if(c->index >= c->completionCount())
                c->index = -1;
            break;
        case Qt::Key_Backtab:
            c->index -= 1;
            if(c->index <= -2)
                c->index = c->completionCount()-1;
            break;
        }
    }

    qDebug() << "Index: " << c->index;

    //bool isShortcut = (e->modifiers() & Qt::ControlModifier) && e->key() == Qt::Key_E;
    bool isShortcut =  e->key() == Qt::Key_Tab || e->key() == Qt::Key_Backtab;
    if(!isShortcut){
        //qDebug() << c->index;
        QTextEdit::keyPressEvent(e);
    }

    if (!c){
        return;
    }

    bool ctrlOrShift = e->modifiers() & (Qt::ControlModifier | Qt::ShiftModifier);
    if (!isShortcut && !ctrlOrShift && e->modifiers() != Qt::NoModifier)
    {
        c->popup()->hide();
        return;
    }
    c->update(this->toPlainText());
    c->popup()->setCurrentIndex(c->completionModel()->index(c->index, 0));
    return;
}


void HtmlDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    QStyleOptionViewItemV4 optionV4 = option;
    initStyleOption(&optionV4, index);

    QStyle *style = optionV4.widget? optionV4.widget->style() : QApplication::style();

    QTextDocument doc;
    doc.setHtml(optionV4.text);

    /// Painting item without text
    optionV4.text = QString();
    style->drawControl(QStyle::CE_ItemViewItem, &optionV4, painter);

    QAbstractTextDocumentLayout::PaintContext ctx;

    // Highlighting text if item is selected
    if (optionV4.state & QStyle::State_Selected)
        ctx.palette.setColor(QPalette::Text, optionV4.palette.color(QPalette::Active, QPalette::HighlightedText));

    QRect textRect = style->subElementRect(QStyle::SE_ItemViewItemText, &optionV4);
    painter->save();
    painter->translate(textRect.topLeft());
    painter->setClipRect(textRect.translated(-textRect.topLeft()));
    doc.documentLayout()->draw(painter, ctx);
    painter->restore();
}

QSize HtmlDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    QStyleOptionViewItemV4 optionV4 = option;
    initStyleOption(&optionV4, index);

    QTextDocument doc;
    doc.setHtml(optionV4.text);
    return QSize(doc.idealWidth(), doc.size().height());
}
